//---------------------------
// Includes
//---------------------------
#include "TrianglePosColor.h"
#include "Level.h"
#include "GraphCamera.h"
//---------------------------
// Defines
//---------------------------
//#define GAME_ENGINE (GameEngine::GetSingleton())

//---------------------------
// Constructor & Destructor
//---------------------------
TrianglePosColor::TrianglePosColor()
:LevelElement()
	,m_pVertexLayout(0)
	,m_pVertexBuffer(0)
	,m_pDefaultEffect(0)	
	,m_pDefaultTechnique(0)	
	,m_pWorldViewProjectionVariable(NULL)
	,m_VertexBufferStride(0)
{
	// nothing to create
}

TrianglePosColor::~TrianglePosColor()
{
	SafeRelease(m_pVertexBuffer );
	SafeRelease(m_pVertexLayout);
}

void TrianglePosColor::Initialize(ContentManager *pContentManager)
{
	CreateEffect(pContentManager);
	DefineInputlayout();
	BuildShape();
	BuildVertexBuffer();
}

void TrianglePosColor::Draw(const RenderContext* pRenderContext)
{
	if(!m_pDefaultTechnique )
	{
		MessageBox(0,_T("No Technique"),_T("ERROR"),0);
		return;
	}
	if(!m_pVertexBuffer)
	{
		MessageBox(0,_T("No Vertices"),_T("ERROR"),0);
		return;
	}	
	// Update Shader matrix variables
	D3DXMATRIX matView = pRenderContext->GetCamera()->GetView();
	D3DXMATRIX matProj = pRenderContext->GetCamera()->GetProj();
	m_pWorldViewProjectionVariable->SetMatrix((float*)&(m_World*matView*matProj));

	// Set the input layout
    m_pLevel->GetDevice()->IASetInputLayout( m_pVertexLayout );

    // Set vertex buffer
    UINT offset = 0;
    m_pLevel->GetDevice()->IASetVertexBuffers( 0, 1, &m_pVertexBuffer, &m_VertexBufferStride, &offset );
   
    // Set primitive topology
    m_pLevel->GetDevice()->IASetPrimitiveTopology( D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST );

    D3D10_TECHNIQUE_DESC techDesc;
    m_pDefaultTechnique->GetDesc( &techDesc );
    for( UINT p = 0; p < techDesc.Passes; ++p )
    {
        m_pDefaultTechnique->GetPassByIndex( p )->Apply(0);
        m_pLevel->GetDevice()->Draw( m_ArrVertices.size(), 0 ); 
    }
}
void TrianglePosColor::CreateEffect(ContentManager *pContentManager)
{
	m_pDefaultEffect = pContentManager->GetEffect(m_pLevel->GetDevice(),  _T("./Effect/color.fx"));
	
	//get first technique found
	m_pDefaultTechnique = m_pDefaultEffect->GetTechniqueByIndex(0);
	if(!m_pDefaultTechnique->IsValid())MessageBox(0,_T("Technique not valid"),_T("ERROR"),0);
		
	GetEffectVariables(m_pDefaultEffect);
}
void TrianglePosColor::GetEffectVariables(ID3D10Effect* pEffect)
{
	//get effect variables
	m_pWorldViewProjectionVariable = pEffect->GetVariableBySemantic("WorldViewProjection")->AsMatrix();
	if(!m_pWorldViewProjectionVariable->IsValid())MessageBox(0,_T("Getting EffectSemantic WorldViewProjection Failed"),_T("ERROR"),0);
}
void TrianglePosColor::DefineInputlayout()
{
    // Define the input layout
    D3D10_INPUT_ELEMENT_DESC layout[] =
    {
        { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D10_INPUT_PER_VERTEX_DATA, 0 },  
        { "COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 12, D3D10_INPUT_PER_VERTEX_DATA, 0 }, 
    };
    UINT numElements = sizeof(layout)/sizeof(layout[0]);

    // Create the input layout
    D3D10_PASS_DESC PassDesc;
	// Get the pass decriptor from the effect technique
    m_pDefaultTechnique->GetPassByIndex( 0 )->GetDesc( &PassDesc );
    HR(m_pLevel->GetDevice()->CreateInputLayout( layout, numElements, PassDesc.pIAInputSignature, PassDesc.IAInputSignatureSize, &m_pVertexLayout ));

	//important set the size of the vertexbuffer, is used in draw base member function
	m_VertexBufferStride = sizeof(VertexPosCol);

}

void TrianglePosColor::BuildShape()
{
	VertexPosCol v1(-3,0,0,1,0,0,1);
	VertexPosCol v2(0,3,0,0,1,0,1);
	VertexPosCol v3(3,0,0,0,0,1,1);
	AddTriangle(v1,v2,v3);
}

void TrianglePosColor::AddTriangle (VertexPosCol v1, VertexPosCol v2, VertexPosCol v3)
{
	m_ArrVertices.push_back(v1);
	m_ArrVertices.push_back(v2);
	m_ArrVertices.push_back(v3);
}

void TrianglePosColor::BuildVertexBuffer()
{
	//fill a buffer description to copy the vertexdata into graphics memory
	D3D10_BUFFER_DESC bd;
	bd.Usage = D3D10_USAGE_DEFAULT;
	bd.ByteWidth = sizeof( VertexPosCol ) * m_ArrVertices.size();
	bd.BindFlags = D3D10_BIND_VERTEX_BUFFER;
	bd.CPUAccessFlags = 0;
	bd.MiscFlags = 0;

	D3D10_SUBRESOURCE_DATA InitData;
	InitData.pSysMem = m_ArrVertices.data();
	//create a ID3D10Buffer in graphics memory containing the vertex info
	HR(m_pLevel->GetDevice()->CreateBuffer( &bd, &InitData, &m_pVertexBuffer ));
}
